Skip to content

Fall back to nextflow_schema.json types for CLI param coercion#7108

Draft
ewels wants to merge 1 commit intonextflow-io:masterfrom
ewels:schema-param-types
Draft

Fall back to nextflow_schema.json types for CLI param coercion#7108
ewels wants to merge 1 commit intonextflow-io:masterfrom
ewels:schema-param-types

Conversation

@ewels
Copy link
Copy Markdown
Member

@ewels ewels commented May 6, 2026

Summary

Under syntax parser v2 (default in 26.04.0), CLI params arrive as strings. Unless the pipeline declares typed params in main.nf or non-null defaults in nextflow.config, those values stay as strings — which breaks param logic that expects e.g. numeric comparison on params.max_cpus.

This change reads property types from nextflow_schema.json (the nf-core convention) when it sits next to main.nf, and uses them to coerce CLI string values before they reach ConfigBuilder. Pipelines that already had a schema get typed params for free with no main.nf changes.

  • New helper: nextflow.config.SchemaParamsHelper
  • One call site: CmdRun.run(), immediately after parsedParams()
  • Walks properties blocks at the top level and under definitions / \$defs / allOf / oneOf / anyOf
  • Coerces string / integer / number / boolean (anything else left untouched)
  • Best-effort: missing or malformed schema is silently ignored; un-coercible values stay as strings
  • Gated on NF.isSyntaxParserV2() and respects NXF_DISABLE_PARAMS_TYPE_DETECTION
Pipeline state Before After
Untyped main.nf, no schema params are strings params are strings (unchanged)
Untyped main.nf, with schema params are strings (broken) typed via schema ✅
Typed params { } in main.nf typed via ParamsDsl typed (no conflict)

Test plan

  • Unit tests for SchemaParamsHelper (12 cases: flat schema, nested definitions/\$defs/allOf, coercion of all four JSON Schema types, malformed schema, missing schema, mixed-case booleans, duplicate-name first-wins, NXF_DISABLE_PARAMS_TYPE_DETECTION opt-out, syntax parser v1 opt-out, pre-typed values from params files, typeless property)
  • End-to-end manual test with a minimal pipeline + nextflow_schema.json confirms --max_cpus 8 --skip_qc TRUE --ratio 0.5 arrive as Integer / Boolean / Float
  • Existing CmdRunTest, ParamsDslTest, and config parser v2 tests still pass

🤖 Generated with Claude Code

Under syntax parser v2, CLI params arrive as strings unless the pipeline
declares typed params in main.nf or non-null defaults in nextflow.config.
This breaks pipelines moving to v26.04.0 that rely on type-coerced params
(e.g. numeric comparisons on `params.max_cpus`).

When a `nextflow_schema.json` lives next to main.nf, read property types
from it and coerce CLI string values before they reach ConfigBuilder.
Coercion is best-effort: missing or malformed schemas are ignored, and
values that don't match a declared type are left untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
@netlify
Copy link
Copy Markdown

netlify Bot commented May 6, 2026

Deploy Preview for nextflow-docs-staging canceled.

Name Link
🔨 Latest commit 95f3e4e
🔍 Latest deploy log https://app.netlify.com/projects/nextflow-docs-staging/deploys/69fb8bc3eb2e360008883ac1

@ewels ewels changed the title Fall back to nextflow_schema.json types for CLI param coercion Fall back to nextflow_schema.json types for CLI param coercion May 6, 2026
@ewels
Copy link
Copy Markdown
Member Author

ewels commented May 6, 2026

Note: duplication with the language server

Note that the Nextflow language server already has equivalent schema-walking code: ParameterSchemaVisitor.java. It walks nextflow_schema.json for IDE type-checking on params.foo accesses, handling the same shape ($defs / defs / definitions / top-level properties) and the same boolean/integer/number/string mapping.

ParameterSchemaVisitor cannot be imported back into Nextflow core — the language server depends on nf-lang, not the other way around — and it returns Groovy AST ClassNode for IDE typing, not runtime values for CLI coercion.

The right consolidation is to lift the schema-walking into the shared nf-lang module as a small utility returning raw param attribute maps (Map<String, Map<String, Object>> — name → {type, default, description, ...}). Then:

  • SchemaParamsHelper (Nextflow core) reads type and coerces
  • ParameterSchemaVisitor (language-server) reads type + default + description and builds ClassNode

Both repos would agree on what counts as a property and which keys the schema is searched under.

If you like, I can re-shape this PR to put the schema reader in nf-lang, then open a parallel language-server PR that switches ParameterSchemaVisitor to consume it. This removes the duplication, but expands scope and is cross-repo (needs an nf-lang version bump on the language-server side once the new Nextflow ships).

static Map<String,String> readSchemaTypes(Path schemaFile) {
try {
final root = new JsonSlurper().parse(schemaFile)
final types = new LinkedHashMap<String,String>()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The types keyword can also be a list of multiple types, how would you handle that case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants